package controllers

import (
	"net/http"
	"fmt"
	"path"
	"os"
	"io/ioutil"
	"time"
	"strings"
  "strconv"
	"crypto/md5"
	"sort"
	"errors"
)

var (
	
	local = os.Getenv("LOCAL_DIR_HOME")
	PathSep = string(os.PathSeparator)

	UrlSep = "/"
	LogicSep = "^"
	
	TimeFormatter = "2006/01/02 15:04"

	Limit = 20

	MinVideoSize, _ = strconv.ParseInt(os.Getenv("MIN_VIDEO_SIZE"), 10, 64)

	scanTime string = time.Unix(0, 0).Format(TimeFormatter)

	// 程序中用到的数据
	dataMap = make(map[string] Item)

	// 有排序的集合
	dataArray = ItemArray {}
)

func init(){
	// 定义Root节点
	root := Item{}
	// add the root
	root.Id = "root"
	root.Path = "/"
	root.Title = "Root"
	root.IsRoot = true
	dataMap["root"] = root

	if MinVideoSize < 1 {
		MinVideoSize = 40
	}
	// scan the root 
	_ScanRoot()
	
}
func Md5(str string) string {
	data := []byte(str)
	has := md5.Sum(data)
	md5str := fmt.Sprintf("%x", has)
	return md5str
}

//---------------------------------------

// 扫描根目录下的文件夹，并深入到文件夹的下一层

func _ScanRoot() {
	// scan the root 
	rows, e := _ListDir("root")
	if e == nil {
		for _, item := range rows {
			if item.ModAt < scanTime {
				continue
			}
			_ListDir(item.Id)
		}
	}

	dataArray = ItemArray {}
	// filte the .mp4 and > 40Mb
	// sort by ModAt Desc
	for _, v := range dataMap {
		if v.IsDir || v.IsRoot {
			continue
		}
		if v.MimeType == ".mp4" && v.Size > MinVideoSize{
			dataArray = append(dataArray, v)
		}
	}
	sort.Sort(dataArray)
	scanTime = time.Now().Format(TimeFormatter)
}

// 读取某个 hash 映射的目录下所有的资源信息，并将信息存储到 dataMap中存储
func _ListDir(hash string) ([]Item, error) {
	// 获取明确的目录地址
	var dirname string
	var pid string
	if IsEmpty(hash) {
		// it's the root
		pid = "root"
	}else{
		pid = hash
	}
	value, ok := dataMap[pid]
	if ok {
		if value.IsRoot {
			dirname = ""
		}else if value.IsDir {
			dirname = value.Path
		}else{
			// The item is not dir
			return nil, errors.New("The hash: " + hash + ". mapped Item is not a directory!")
		}
		
	}

	dir_list, e := ioutil.ReadDir(local + dirname)
	if e != nil {
		//return nil
		return nil, errors.New("directory path may error: " + local + dirname)
	}
	items := []Item{} 
	for _, v := range dir_list {
		// 以 . 开头的文件或目录通常是隐藏的，直接过滤掉
		if strings.HasPrefix(v.Name(), "."){
			continue
		}
		item := Item{}
		item.Pid = pid
		item.Title = v.Name()
		item.Size = v.Size() / 1024 / 1024
		item.Path = dirname + PathSep + v.Name()
		item.Id = Md5(item.Path)
		item.IsDir = v.IsDir()
		// item.Url = "/item?id=" + item.Id

		if item.IsDir {
			item.MimeType = ".dir"
			item.ModAt = v.ModTime().Format(TimeFormatter)
		}else{
      item.ModAt = v.ModTime().Format(TimeFormatter)
			item.MimeType = path.Ext(item.Path)
		}

		items = append(items, item)
		// Add to dataMap
		dataMap[item.Id] = item
	}
	return items, nil
}

// list handler 
func DetailHandler(w http.ResponseWriter, r *http.Request) {
	// pagination
	var keywords, page string
	ok := false
	params := _ParseUrlParams(r)
	keywords, ok = params["keywords"]
	if !ok {
		keywords = ""
	}
	page, ok = params["page"]
	if !ok {
		page = "1"
	}
	pageNum, err := strconv.Atoi(page)
	if err != nil {
		panic(err)
	}
	var filtedArray []Item
	if !IsEmpty(keywords) {
		filtedArray = []Item{}
		for _, v := range dataArray {
			if strings.Index(v.Title, keywords) > -1{
				filtedArray = append(filtedArray, v)
			}
		}
	}else {
		filtedArray = dataArray
	}
	
	filtedArray, hasPre, hasNext := _MakePager(filtedArray, pageNum)

	// dataArray
	RenderTemplate(w, "directory.html", map[string]interface{}{ "rows": filtedArray, "hasPre": hasPre, "hasNext": hasNext, "keywords": keywords, "prePage": pageNum - 1, "nextPage": pageNum + 1 , "IsPreview": true} )
}

func PreviewHandler(w http.ResponseWriter, r *http.Request) {
	
	r.ParseForm()
	var id, preview string
	var parent Item
	if len(r.Form["id"]) > 0 {
		id = r.Form["id"][0]
	}
	if len(r.Form["preview"]) > 0 {
		preview = r.Form["preview"][0]
	}
	if IsEmpty(id) {
		id = "root"
	}
	if IsEmpty(preview) {
		preview = "0"
	}
	item, ok := dataMap[id]
	if !ok {
		http.Error(w, "error 500:" + " " + "The Id not existed", http.StatusInternalServerError)
		return
	}

	// get parent info
	if !item.IsRoot && preview == "1" {
		parent = dataMap[item.Pid]
	}
	if item.IsRoot || item.IsDir {
		// dir
		items, err := _ListDir(id)
		if err != nil {
			http.Error(w, "error 500:" + " " + err.Error(), http.StatusInternalServerError)
			return
		}
		RenderTemplate(w, "directory.html", map[string]interface{}{ "item": item, "children": items, "parent": parent } )
	}else{
		// increase the view of the item
		item.Views = item.Views + 1
		dataMap[item.Id] = item
		RenderTemplate(w, "review.html", map[string]interface{}{ "item": item, "parent": parent, "preview": preview } )
	}
}